#include "CGame.h"
#include "CDungeonFloor.h"

CDungeonFloor::~CDungeonFloor()
{
	Entities.clear();
	delete FovMap;
}

bool CDungeonFloor::isTile(pair position)
{
	return (position.x() >= 0 && position.x() < (int)FloorTiles.size()
		&& position.y() >= 0 && position.y() < (int)FloorTiles[position.x()].size());
}

CDungeonTile* CDungeonFloor::getTile(pair position)
{
	return &FloorTiles[position.x()][position.y()];
}

CEntity* CDungeonFloor::getEntityAt(pair position)
{
	for (unsigned int i = 0; i < Entities.size(); ++i)
		if (Entities[i]->getPosition() == position)
			return Entities[i];

	return NULL;
	//return EntityLocations[position];
}

TCODMap* CDungeonFloor::getFovMap()
{
	return FovMap;
}

pair CDungeonFloor::getSize()
{
	return Size;
}

void CDungeonFloor::generate(int thisFloor, pair size, CDungeonFloor* floorAbove)
{
	Size = size;

	FloorTiles.resize(Size.x(), std::vector<CDungeonTile>(Size.y()));
	FovMap = new TCODMap(Size.x(), Size.y());

	GenerateCellularAutomata(1, 50);

	while (Entities.size() < 30)
	{
		CEntity* kbld = new CEntity("Kobold");
		kbld->setAttribute("Strength", 8);
		kbld->setAttribute("Endurance", 8);
		kbld->init("Kobold");
		CTurnSchedule::scheduleTurn(0, kbld);
		Entities.push_back(kbld);
		FloorTiles[kbld->getPosition().x()][kbld->getPosition().y()].entities.push_back(kbld);
	}

	while (Items.size() < 15)
	{
		CItem* item = new CItem();

		bool placed = false;
		pair pos;
		while (!placed)
		{
            pos = pair(TCODRandom::getInstance()->getInt(1, size.x()-1), TCODRandom::getInstance()->getInt(1, size.y()-1));
            if (FloorTiles[pos.x()][pos.y()].isPassable())
                placed = true;
		}

		item->createOnGround(CItem::getRandomItem(), '!', pos);
		FloorTiles[pos.x()][pos.y()].items.push_back(item);
		Items.push_back(item);
	}

	for (unsigned int x = 0; x < FloorTiles.size(); ++x)
	{
		for (unsigned int y = 0; y < FloorTiles[x].size(); ++y)
		{
			if (FloorTiles[x][y].isPassable())
				FovMap->setProperties(x, y, true, true);
			else
				FovMap->setProperties(x, y, false, false);
		}
	}

	saveDungeonToFile("dungeon.txt");
}

void CDungeonFloor::saveDungeonToFile(std::string fileName)
{
	std::ofstream file((std::string("data/dungeons/")+fileName).c_str());
	for (unsigned int x = 0; x < FloorTiles.size(); ++x)
	{
		for (unsigned int y = 0; y < FloorTiles[x].size(); ++y)
		{
			file << FloorTiles[x][y].getShape();
		}
		file << std::endl;
	}
	file.close();
}

void CDungeonFloor::update()
{
    for (unsigned int i = 0; i < Entities.size(); ++i)
		if (Entities[i]->isDead())
		{
			for (unsigned int j = 0; j < FloorTiles[Entities[i]->getPosition().x()][Entities[i]->getPosition().y()].entities.size(); ++j)
				if(FloorTiles[Entities[i]->getPosition().x()][Entities[i]->getPosition().y()].entities[j] == Entities[i])
					FloorTiles[Entities[i]->getPosition().x()][Entities[i]->getPosition().y()].entities.erase(FloorTiles[Entities[i]->getPosition().x()][Entities[i]->getPosition().y()].entities.begin()+j);

			Entities.erase(Entities.begin()+i);
		}
}

void CDungeonFloor::GenerateCellularAutomata(unsigned int iterations, unsigned int percentWalls)
{
	unsigned int rnd = TCODRandom::getInstance()->getInt(1, 100);
	for (unsigned int x = 1; x < FloorTiles.size()-1; ++x)
	{
		for (unsigned int y = 1; y < FloorTiles[x].size()-1; ++y)
		{
			if (rnd > percentWalls)
			{
				FloorTiles[x][y].setShape('.');
				FloorTiles[x][y].setName("Floor");
				FloorTiles[x][y].setPassable(true);
				FovMap->setProperties(x, y, true, true);
			}

			rnd = TCODRandom::getInstance()->getInt(1, 100);
		}
	}

	for (unsigned int i = 0; i < iterations; ++i)
	{
		for (unsigned int x = 0; x < FloorTiles.size(); ++x)
		{
			for (unsigned int y = 0; y < FloorTiles[x].size(); ++y)
			{
				if (x == 0 || x == FloorTiles.size()-1 || y == 0 || y == FloorTiles[x].size()-1)
				{
					FloorTiles[x][y].setShape('#');
					FloorTiles[x][y].setName("Wall");
					FloorTiles[x][y].setPassable(false);
					FovMap->setProperties(x, y, false, false);
				}
				else
				{
					int w = 0;
					if (FloorTiles[x-1][y-1].getShape() == '#')
						w++;
					if (FloorTiles[x-1][y].getShape() == '#')
						w++;
					if (FloorTiles[x-1][y+1].getShape() == '#')
						w++;
					if (FloorTiles[x][y-1].getShape() == '#')
						w++;
					if (FloorTiles[x][y].getShape() == '#')
						w++;
					if (FloorTiles[x][y+1].getShape() == '#')
						w++;
					if (FloorTiles[x+1][y-1].getShape() == '#')
						w++;
					if (FloorTiles[x+1][y].getShape() == '#')
						w++;
					if (FloorTiles[x+1][y+1].getShape() == '#')
						w++;

					if (w > 4)
					{
						FloorTiles[x][y].setShape('#');
						FloorTiles[x][y].setName("Wall");
						FloorTiles[x][y].setPassable(false);
						FovMap->setProperties(x, y, false, false);
					}
					else
					{
						FloorTiles[x][y].setShape('.');
						FloorTiles[x][y].setName("Floor");
						FloorTiles[x][y].setPassable(true);
						FovMap->setProperties(x, y, true, true);
					}
				}
			}
		}
	}
}

